﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using swiftpass.utils;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Xml;
using System.Web.Script.Serialization;
using System.Text;

namespace WFTpayInterface
{
    public partial class Index : System.Web.UI.Page
    { 
        private ClientResponseHandler resHandler = new ClientResponseHandler();
        private PayHttpClient pay = new PayHttpClient();
        private RequestHandler reqHandler = null;
        private Dictionary<string, string> cfg = new Dictionary<string, string>(1);
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                this.tbout_trade_no.Text = Utils.Nmrandom();//商户订单号 
                //this.tbmch_create_ip.Text = Request.UserHostAddress;
               
                string userHostAddress = HttpContext.Current.Request.UserHostAddress;
                
                if (string.IsNullOrEmpty(userHostAddress))
                {
                    userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }
               
                if (string.IsNullOrEmpty(userHostAddress))
                {
                    userHostAddress = HttpContext.Current.Request.UserHostAddress;
                }
                //最后判断获取是否成功，并检查IP地址的格式（检查其格式非常重要）
                if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress))
                {
                       this.tbmch_create_ip.Text = userHostAddress;
                }
                else{
                  this.tbmch_create_ip.Text =  "123.12.12.123";
                }
            }
        }
        /// <summary>
        /// 检查IP地址格式
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>  
        public static bool IsIP(string ip)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }
        /// <summary>
        /// 订单提交
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnok_Click(object sender, EventArgs e)
        {
            txt_err.Text="";
            btnqueren.Visible = true;
            
            if (tbtotal_fee.Text == "0")
            {
                Response.Write("<script>alert('总金额不能为【0】！')</script>");
            }
            else
            {                
                this.reqHandler = new RequestHandler(null);
                //加载配置数据
                this.cfg = Utils.loadCfg();
                this.reqHandler.setGateUrl(this.cfg["req_url"].ToString());
                //this.reqHandler.setKey(this.cfg["key"].ToString());
                this.reqHandler.setParameter("auth_code", auth_code.Text);//付款授权码
                this.reqHandler.setParameter("out_trade_no", tbout_trade_no.Text);//商户订单号
                this.reqHandler.setParameter("body", tbbody.Text);//商品描述
                this.reqHandler.setParameter("sign_type", "RSA_1_1");//签名方式
                this.reqHandler.setParameter("attach", tbattach.Text);//附加信息
                this.reqHandler.setParameter("total_fee", tbtotal_fee.Text);//总金额
                this.reqHandler.setParameter("mch_create_ip", tbmch_create_ip.Text);//终端IP
                this.reqHandler.setParameter("time_start", tbtime_start.Text); //订单生成时间
                this.reqHandler.setParameter("time_expire", tbtime_expire.Text);//订单超时时间
                this.reqHandler.setParameter("service", "unified.trade.micropay");//接口类型： 
                this.reqHandler.setParameter("mch_id", this.cfg["mch_id"].ToString());//必填项，商户号，由平台分配
                this.reqHandler.setParameter("version", this.cfg["version"].ToString());//接口版本号
                this.reqHandler.setParameter("nonce_str", Utils.random());//随机字符串，必填项，不长于 32 位
                this.reqHandler.createSign();//创建签名
                //以上参数进行签名
                string data = Utils.toXml(this.reqHandler.getAllParameters());//生成XML报文
                Dictionary<string, string> reqContent = new Dictionary<string, string>();
                reqContent.Add("url", this.reqHandler.getGateUrl());
                reqContent.Add("data", data);
                this.pay.setReqContent(reqContent);
                if (this.pay.call())
                {
                    this.resHandler.setContent(this.pay.getResContent());
                    //this.resHandler.setKey(this.cfg["key"].ToString());
                    Hashtable param = this.resHandler.getAllParameters();
                    if (int.Parse(param["status"].ToString()) == 0)
                    {
                        if (this.resHandler.isTenpaySign())
                        {
                            /*当调用支付接口后各个情况的处理可参考如下方案：
                                1、 支付请求后：status和result code字段返回都为0时，判定订单支付成功；
                                2、 支付请求后：status返回为0，result code返回不为0时，根据返回字段“need query ”来判定：
                                ①“need query” 返回为 Y  则调用订单查询接口（建议 ：查询6次每隔5秒查询一次 ，具体的查询次数和时间也可自定义，建议查询时间不低于30秒）6次查询走完， 接口仍未返回成功标识(即查询接口返回的trade_state不是等于SUCCESS)则调用冲正接口进行 关单；
                                3、在status字段返回都为不为0时，建议也调用订单查询接口，调用建议方式如第2点
                             *  4、如果没有返回need query参数，先输出错误信息，再通过人工判断是否手动继续执行查询；建议开发一个手动查询功能，避免特殊情况的返回结果。
                             * 
                             */
                            #region 逻辑处理
                            Utils.writeFile("请求响应结果日志", param);
                            if (int.Parse(param["status"].ToString()) != 0)
                            {
                                if (param["message"] != null)
                                {
                                    txt_err.Text = param["message"].ToString();
                                }
                                else if (param["err_msg"] != null)
                                {
                                    txt_err.Text = param["err_msg"].ToString();
                                }
                                else { }
                                if (param["need_query"] != null)
                                {
                                    if (param["need_query"].ToString() != "N")
                                    {
                                        txt_err.Text = "确认顾客情况后，需要手动查询结果！";
                                    }
                                }
                            }
                            if (int.Parse(param["status"].ToString()) == 0 && int.Parse(param["result_code"].ToString()) != 0)
                            {
                                if (param["message"] != null)
                                {
                                    txt_err.Text = param["message"].ToString();
                                }
                                else if (param["err_msg"] != null)
                                {
                                    txt_err.Text = param["err_msg"].ToString();
                                }
                                else { }
                                if (param["need_query"] != null)
                                {
                                    if (param["need_query"].ToString() != "N")
                                    {
                                        txt_err.Text = "确认顾客情况后，需要手动查询结果！";
                                    }
                                }

                            }
                            #endregion
                            if (int.Parse(param["status"].ToString()) == 0 && int.Parse(param["result_code"].ToString()) == 0)
                            {
                                //更新商户订单系统DB,提示成功或跳转完成页面。
                                //Response.Redirect("payCode.aspx"); 
                                txt_err.Text = "支付成功！";
                                
                            }
                        }
                    }
                    else
                    {
                        Utils.writeFile("请求响应结果日志", param);
                        Response.Write("<script>alert('返回结果校验签名错误，请检查签名算法及核查结果内容是否正确！')</script>");
                    }
                }
                else
                {
                    txt_err.Text = "错误代码：" + this.pay.getResponseCode() + "错误信息：" + this.pay.getErrInfo();
                }
                
            }
        } 
        #region 手动查询结果 
        private string SelectPayCMD()
        {
            this.reqHandler = new RequestHandler(null);
            //加载配置数据
            this.cfg = Utils.loadCfg(); ;
            //初始化数据 
            this.reqHandler.setGateUrl(this.cfg["req_url"].ToString());
            //this.reqHandler.setKey(this.cfg["key"].ToString());
            this.reqHandler.setParameter("out_trade_no", tbout_trade_no.Text);//商户订单号             
            this.reqHandler.setParameter("service", "unified.trade.query");//接口 unified.trade.query 
            this.reqHandler.setParameter("mch_id", this.cfg["mch_id"].ToString());//必填项，商户号，由平台分配
            this.reqHandler.setParameter("version", this.cfg["version"].ToString());//接口版本号
            this.reqHandler.setParameter("sign_type", "RSA_1_1");//签名方式
            this.reqHandler.setParameter("nonce_str", Utils.random());//随机字符串，必填项，不长于 32 位
            this.reqHandler.createSign();//创建签名
            //以上参数进行签名
            string sdata = Utils.toXml(this.reqHandler.getAllParameters());//生成XML报文
            Dictionary<string, string> sreqContent = new Dictionary<string, string>();
            sreqContent.Add("url", this.reqHandler.getGateUrl());
            sreqContent.Add("data", sdata);
            this.pay.setReqContent(sreqContent);
            this.pay.call();
            this.resHandler.setContent(this.pay.getResContent());
            this.resHandler.setKey(this.cfg["key"].ToString());
            Hashtable sparam = this.resHandler.getAllParameters();
            //当返回状态与业务结果都为0时才返回结果，其它结果请查看接口文档
            if (int.Parse(sparam["status"].ToString()) == 0 && int.Parse(sparam["result_code"].ToString()) == 0)
            {
                //查询订单成功更新商户订单系统DB,结束轮询机制
                return sparam["trade_state"].ToString();
            }
            else
            {
                if (sparam["message"] != null)
                {
                    return sparam["message"].ToString();
                }
                else if (sparam["err_msg"] != null)
                {
                    return sparam["err_msg"].ToString();
                }
                else
                {
                    return "";
                }
            }

        }
        #endregion
        private bool  ReserveOrder()
        {
            this.reqHandler = new RequestHandler(null);
            //加载配置数据
            this.cfg = Utils.loadCfg(); ;
            //初始化数据 
            this.reqHandler.setGateUrl(this.cfg["req_url"].ToString());
            //this.reqHandler.setKey(this.cfg["key"].ToString());
            this.reqHandler.setParameter("out_trade_no", tbout_trade_no.Text);//商户订单号             
            this.reqHandler.setParameter("service", "unified.micropay.reverse");//接口 unified.micropay.reverse
            this.reqHandler.setParameter("mch_id", this.cfg["mch_id"].ToString());//必填项，商户号，由平台分配
            this.reqHandler.setParameter("version", this.cfg["version"].ToString());//接口版本号
            this.reqHandler.setParameter("sign_type", "RSA_1_1");//签名方式
            this.reqHandler.setParameter("nonce_str", Utils.random());//随机字符串，必填项，不长于 32 位
            this.reqHandler.createSign();//创建签名
            //以上参数进行签名
            string sdata = Utils.toXml(this.reqHandler.getAllParameters());//生成XML报文
            Dictionary<string, string> sreqContent = new Dictionary<string, string>();
            sreqContent.Add("url", this.reqHandler.getGateUrl());
            sreqContent.Add("data", sdata);
            this.pay.setReqContent(sreqContent);
            this.pay.call();
            this.resHandler.setContent(this.pay.getResContent());
            //this.resHandler.setKey(this.cfg["key"].ToString());
            Hashtable sparam = this.resHandler.getAllParameters();
            //当返回状态与业务结果都为0时才返回结果，其它结果请查看接口文档
            if (int.Parse(sparam["status"].ToString()) == 0 && int.Parse(sparam["result_code"].ToString()) == 0)
            {
                 //冲正成功
                return true;
            }
            else
            { 
                return false;
            } 
        }
        //查询结果
        protected void btnqueren_Click(object sender, EventArgs e)
        {
            txt_err.Text="";
            string result=SelectPayCMD();//查询结果赋值
            //判断结果值输出对应提示。
            if (result == "SUCCESS")
            { 
                txt_err.Text="支付成功！"; 

            }
            else if (result == "REVOKED")
            { 
                txt_err.Text="已冲正！"; 
            }
            else if (result == "NOTPAY")
            { 
                txt_err.Text="未支付！";
                btnrevoke.Visible = true;//如果顾客实际已支付而查询结果是未支付，可执行冲正
            }
            else if (result == "PAYERROR")
            {
                txt_err.Text = "支付失败！";
                btnrevoke.Visible = true;//如果顾客实际已支付而查询结果是支付失败，也可执行冲正
            }
            else if (result == "订单不存在")
            { 
                txt_err.Text="订单未提交确认支付！"; 
            }
            else
            {
                txt_err.Text=result; 
            }
        }
        //冲正
        protected void btnrevoke_Click(object sender, EventArgs e)
        {
            //执行冲正得出结果是否为正确
            if (ReserveOrder())
            {
                txt_err.Text="冲正成功！"; 
            }
            else
            {
                txt_err.Text="冲正失败，请继续！"; 
            } 
        } 
    }
}